# -*- shell-script -*-
#
# "Tank" Simulation
#

record(ao, "$(user):room")
{
    field(DESC, "Room Temperature")
    field(EGU, "C")
    field(HOPR, "100")
    field(LOPR, "0")
    field(DRVL, "0")
    field(DRVH, "100")
    field(DOL, "25")
    field(PINI, "YES")
}

# This ao is used in two modes:
# supervisory: user can adjust voltage
# closed_loop: PID (in separate control.db) sets voltage
# In any case: Update heater power in response to voltage change
# When PID is INVALID, go back to 0 voltage
record(ao, "$(user):heat_V")
{
    field(DESC, "Heater Voltage")
    field(EGU, "V")
    field(DRVL,"0")
    field(DRVH,"110")
    field(HSV, "MINOR")
    field(HIGH,"110")
#   Set by control.db
#   field(DOL, "$(user):PID MS")
#   field(OMSL,"closed_loop")
    field(IVOA, "Set output to IVOV")
    field(IVOV, "0")
}

record(calc, "$(user):heat_Pwr")
{
    field(DESC, "Heater Power")
    field(EGU, "W")
    field(INPA, "$(user):heat_V PP NMS")
# ~1000 Watt heater when run with 110V:
# P = U I = U^2 / R,  R~12 Ohm
    field(CALC, "A*A/12.1")
}

# Every second, calculate new temperature
# based on current temperature,
# room temperature and heater
#
# A - current temperature
# B - room temperature
# C - heater power
# D - isolation factor (water <-> room)
# E - heat capacity (would really depend on water volume)
#
# Very roughly with
# T(n+1) = T(n) + [Troom-T(n)]*Isolation_factor + heater_pwr * heat_capacity
record(calc, "$(user):tank_clc")
{
    field(DESC,"Water Tank Simulation")
# Water temperatures in deg. C go from 0 to 100 degC
    field(SCAN,".5 second")
    field(INPA,"$(user):tank_clc.VAL")
    field(INPB,"$(user):room")
    field(INPC,"$(user):heat_Pwr PP NMS")
    field(INPD,"0.01")
    field(INPE,"0.001")
    field(PREC,"4")
    field(CALC,"A+(B-A)*D+C*E")
    field(FLNK,"$(user):tank")
}

# Simulate "broken sensor"
record(bi, "$(user):sensor")
{
    field(DESC, "Sensor Simulation")
    field(ZNAM, "OK")
    field(ONAM, "Broken")
    field(OSV,  "MAJOR")
    field(PINI, "YES")
    field(FLNK, "$(user):tank")
}

# Tank temperature as measured by
# (possibly broken) sensor
record(calc, "$(user):tank")
{
    field(DESC, "Tank Temperature or INVALID")
    field(EGU,  "C")
    field(PREC, "1")
    field(LOPR, "0")
    field(HOPR, "100")
    field(LOLO, "-100")
    field(LOW,  "0")
    field(HIGH, "70")
    field(HIHI, "100")
    field(LLSV, "INVALID")
    field(LSV,  "MINOR")
    field(HSV,  "MINOR")
    field(HHSV, "MAJOR")
    field(INPA, "$(user):sensor")
    field(INPB, "$(user):tank_clc MS")
    field(INPC, "-100")
    field(CALC, "A?C:B")
}

